\chapter{\label{sec:Multiple-Users}多用户模式}

\section{简介}
在上一个章节中我只用了一个用户（我）来概述了Fossil的使用。在这节中我们将会学习在多个用户的情况下如何使用。感谢Fossil的分布式设计，一旦完成设置在多用户Fossil自动管理模式下的使用方式和单用户模式下没有多大的区别。

\section{设置}
在上一节中Fossil仓库是一个我们操作系统里的一个文件，我们对这个文件进行提交代码和拉取源代码操作。Fossil是一个分布式的源码控制系统；这意味着存在一个所有用户都可以连接的主仓库。每一个用户在本地都拥有他们自己``cloned''的仓库副本，使用的命令和上一个章节\ref{sec:Single-User-Fossil}一样。现在不同的是Fossil将要把你的仓库和主仓库自动进行同步。

\subsection{服务器设置\label{sub:Server-Setup}}
我有一个叫FossilBook.fossil的仓库，现在要把它放在某个多个用户可以访问的地方。有二个方式，第一个是使用Fossil内建的网络服务器来托管这个文件，另外一个是使用操作系统支持的网站服务器和一个CGI类型的链接来托管（如果存在）。

\paragraph{自托管}
这是一个非常简单方式，下面就是可靠的保持机器存在且网络服务器已经启动。就这么多，当你完成一天的工作时不要关闭电脑，因为其他的用户可能需要使用它来上传代码，所有我要做的如下：

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize {[}Pandora-2:/Users/jschimpf/Public{]}~jim\%~cd~FOSSIL/}{\scriptsize \par}
{\scriptsize {[}Pandora-2:jschimpf/Public/FOSSIL{]}~jim\%~}\textbf{\scriptsize fossil~ui~-port~8081~FossilBook.fossil~\&}{\scriptsize{}~}{\scriptsize \par}
{\scriptsize {[}1{]}~310}{\scriptsize \par}
{\scriptsize {[}Pandora-2:jschimpf/Public/FOSSIL{]}~jim\%~}{\scriptsize \par}
\end{lyxcode}
\caption{自托管的Fossil仓库}
\end{figure}

这个是在UNIX系统里，在倒数第二行的``\&''符号表示将Fossil的网络服务器在后台运行。如果你知道这台电脑有IP地址如192.168.1.200，那么在另外在同一个网络的机器上输入：

\textbf{http://192.168.1.200:8081} 浏览器打开这个链接，那么我就可以访问Fossil的网页界面了。

如你所见，这个很简单且可以运行在任何运行Fossil的操作系统中。你必须仔细确认它一直在运行且对于其它用户可访问，那么这就是一个非常简单的方式来保障主仓库的存在。 

这个方法的问题是：
\begin{enumerate}
\item 如果你有多个仓库，你不得不使用\textbf{server}而不是 \textbf{ui}命令，且将所有的仓库都存放在一个目录下面。且它们都必须以后缀.fossil格式保存。
\item 如果电脑离线（比如:需要操作系统升级）或者其它原因无法自动重启Fossil服务器。
\item 仓库备份将无法实现。
\end{enumerate}
这个方法可以工作，如果你只有一个仓库且主仓库的使用者足够勤奋努力，而且也会工作得很好。


\paragraph{服务器托管}

如果你有一个服务器类型的机器（比如：Linux或UNIX）可以运行Apache或者装有IIS的Windows机器，你可以使用它们作为你的仓库的网络服务器。这样有大量的优势：这个机器将会一直在线，而且会自动备份，并且可以很容易地实现多个Fossil仓库的托管。

我不打算深入如何设置网站服务器或者如何开启CGI，你可以查下如下网站
\begin{itemize}
\item Windows IIS 查看 \url{http://www.boutell.com/newfaq/creating/iiscgihowto.html} 只要保证你的fossil.exe在CGI脚本可以运行的路径里。
\item Apache 查看这里 \url{http://httpd.apache.org/docs/2.0/howto/cgi.html}保证你知道CGI脚本保存在什么的地方。
\end{itemize}
如果你无法控制网站服务器，那么你需要服务器管理员的帮助开启CGI并将你的CGI脚本复制到正确的位置。


\paragraph{托管服务器的CGI脚本}

如果我们采用Apache服务器，就是我的方式，那么CGI目录位于 /Library/Webserver/CGI-Executables，然后我们需要写入如下的脚本：

\begin{figure}[H]
\begin{lyxcode}
\#!<Fossil~executable~location>
repository:~<Fossil~repository~location>
\end{lyxcode}
\caption{Fossil CGI脚本}
\end{figure}

然后把它放入CGI脚本目录。我将我的Fossil可执行文件放在目录/usr/local/binFossil仓库的共享的目录放在了/Users/Shared/FOSSIL。那么我的脚本应该作如下变化：

\begin{figure}[H]
\begin{lyxcode}
\#!/usr/local/bin/fossil
\#~Put~the~book~repository~on~the~web
repository:~/Users/Shared/FOSSIL/Fossilbook.fossil
\end{lyxcode}
\caption{My Fossil CGI脚本}
\end{figure}


在完成脚本后，我把它复制到了CGI目录并允许任何人允许它。

\begin{figure}[H]
\begin{lyxcode}
\textbf{\scriptsize sudo~cp~Book.cgi~/Library/Webserver/CGI-Executables/Book.cgi}{\scriptsize \par}
\textbf{\scriptsize sudo~chmod~a+x~/Library/Webserver/CGI-Executables/Book.cgi}{\scriptsize \par}
\end{lyxcode}
\caption{复制脚本到指定位置}
\end{figure}

\subsection{测试(含自托管和服务器托管)}

如果所有文件都在正确位置那么我现在应该可以访问网站服务器且他会将我带到如下界面：
\begin{figure}[H]
\includegraphics[scale=0.5]{Images/Multiple_user/test_access}
\caption{\label{fig:Web-access-to}网络访问Fossil CGI托管的网站}
\end{figure}

\section{用户账户}

为一个仓库提供网络服务，不管是自托管还是复杂的CGI方式，都会将你带到同一个地方，如图示\vref{fig:Web-access-to}所见。现在我需要设置用户账户以方便其它贡献者为我的书提交代码或者修改。记住Fossil已经自动创建了一个匿名用户（见图示\vref{fig:User-Configuration}）。其它人可以在有限制的情况下访问这个网站，默认匿名用户可以下载这本书但是不能提交修改。在这个项目组我打算创建一个新账户（Marilyn）且这个账户可以修改及提交修改，因为她是我的编辑。

为了完成所有这些操作我需要在登陆界面输入我的ID(Jim)及我的密码。现在我是超级用户，我可以回到用户配置页面，图示\eqref{fig:User-Configuration}然后添加一个新用户：

\begin{figure}[H]
\includegraphics[scale=0.5]{Images/Multiple_user/mul_new_user}
\caption{新编辑用户\label{fig:New-Editor-user}}
\end{figure}

我打算把她设置为一个编辑，如果我们需要编写代码那么需要她作为一个类似开发者的角色，所以我为其选择了开发人员特权的级别。这样的话她就可以对仓库执行check-in、check-out和写和更新标签的操作。我还添加了添加附件的权限，因为考虑到她需要做些如放图片及其它评论类的操作。我还给她设置了一个密码，那么她的连接将会被密码保护。

在这里，我还可以添加其它的用户但是该项目不要其它的人员了，但是你可以看到这个操作是多么的简单了。当你指派给用户权限的时候只要仔细阅读并保证不要给他们你认为不需要的功能。如果他们有问题，你可以在将来给他们做简单的修改就可以了。


\section{多用户运行}

当服务器已经设置完成并在运行，下一步用户确定需要做的就是Clone这个仓库。这个操作的就是从网站服务器将仓库复制到我的本地机器。一旦完成Clone操作后，使用这个仓库的方式和单用户使用模式\vref{sec:Single-User-Fossil}下的操作命令几乎一模一样。Fossil将同步你的本地仓库到服务器。


\subsection{克隆}

在Clone一个Fossil仓库之前，你需要知道下面四个事情：
\begin{enumerate}
\item 网站地址，我们目前的仓库地址是 \textbf{http://pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi}
\item 你的账户名称，我的例子中是\textbf{jim}
\item 你的密码（我还是不会告诉你的）
\item 本地仓库的名称，在本书的例子里叫Fossilbook.fossil
\end{enumerate}
然后你可以在任何你想要保存仓库的目录（本书例子的目录是FOSSIL）里运行如下克隆命令

\begin{figure}[H]
\begin{lyxcode}
{\tiny {[}Pandora-2:jschimpf/Public/FOSSIL{]}}\textbf{\tiny{}~fossil~clone~http://jim:}{\tiny <passwd>}\textbf{\tiny @pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi~FossilBook.fossil}{\tiny \par}

\textbf{\scriptsize \#\#\#~NOTE:~<passwd>~}{\scriptsize -~Stands~in~for~real~password}{\scriptsize \par}



{\scriptsize{}~~~~~~~~~~~~~~~Bytes~~~~~~Cards~~Artifacts~~~~~Deltas}{\scriptsize \par}

{\scriptsize Send:~~~~~~~~~~~~~~49~~~~~~~~~~1~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Received:~~~~~~~~~120~~~~~~~~~~2~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Send:~~~~~~~~~~~~~625~~~~~~~~~25~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Received:~~~~~~~~4704~~~~~~~~~72~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Send:~~~~~~~~~~~~3104~~~~~~~~~72~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Received:~~~~~5129052~~~~~~~~131~~~~~~~~~10~~~~~~~~~~5}{\scriptsize \par}

{\scriptsize Send:~~~~~~~~~~~~2399~~~~~~~~~51~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Received:~~~~~4381170~~~~~~~~116~~~~~~~~~22~~~~~~~~~28}{\scriptsize \par}

{\scriptsize Total~network~traffic:~4117~bytes~sent,~6913068~bytes~received}{\scriptsize \par}

{\scriptsize Rebuilding~repository~meta-data...}{\scriptsize \par}

{\scriptsize 65~(100\%)...}{\scriptsize \par}

{\scriptsize project-id:~2b0d35831c1a5b315d74c4fd8d532b100b822ad7}{\scriptsize \par}

{\scriptsize server-id:~~3e67da6d6212494456c69b1c5406a277d7e50430}{\scriptsize \par}

{\scriptsize admin-user:~jim~(password~is~\textquotedbl{}d07222\textquotedbl{})}{\scriptsize \par}

{\scriptsize {[}Pandora-2:jschimpf/Public/FOSSIL{]}~jim\%~}{\scriptsize \par}
\end{lyxcode}
\caption{Clone命令}


\end{figure}


在这里我可以参考章节\vref{sec:Single-User-Fossil}的步骤来设置我的用户密码，然后将仓库在一个工作文件夹内打开。

现在我已经把所有的东西转移到了新克隆的仓库里，我在完成一天工作后的检入操作如下所示：

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%~}\textbf{\scriptsize fossil~commit~-m~\textquotedbl{}Moved~to~clone~repository\textquotedbl{}}{\scriptsize \par}

{\scriptsize Autosync:~http://jim@pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi}{\scriptsize \par}

{\scriptsize Bytes~Cards~Artifacts~Deltas}{\scriptsize \par}

{\scriptsize Send:~130~1~0~0}{\scriptsize \par}

{\scriptsize Received:~2990~65~0~0}{\scriptsize \par}

{\scriptsize Total~network~traffic:~334~bytes~sent,~1876~bytes~received}{\scriptsize \par}

{\scriptsize New\_Version:~158492516c640d055bc0720684a05e797b88165a}{\scriptsize \par}

{\scriptsize Autosync:~http://jim@pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi}{\scriptsize \par}

{\scriptsize Bytes~Cards~Artifacts~Deltas}{\scriptsize \par}

{\scriptsize Send:~618798~74~1~2}{\scriptsize \par}

{\scriptsize Received:~3222~70~0~0}{\scriptsize \par}

{\scriptsize Send:~268138~73~1~0}{\scriptsize \par}

{\scriptsize Received:~3221~70~0~0}{\scriptsize \par}

{\scriptsize Send:~3977~72~0~1}{\scriptsize \par}

{\scriptsize Received:~3220~70~0~0}{\scriptsize \par}

{\scriptsize Total~network~traffic:~457995~bytes~sent,~6011~bytes~received}{\scriptsize \par}

{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%~}{\scriptsize \par}
\end{lyxcode}
\caption{\label{fig:Cloned-repository-checkin}克隆仓库的检入}


\end{figure}


如你所见文件被提交到了本地仓库然后本地仓库自动与服务器进行了同步。


\subsection{保持同步}

在完成了所有上文所描述的设置工作后，我现在拥有了一个分布式的源码控制系统。我的合作者Marilyn也已经克隆仓库并开始工作了。她在编辑病修正书中我语句不通顺或者有拼写有误的地方。她独立地工作在同一个且同时被我在使用的文件。我们必须使用Fossil来阻止我们同时编辑FossilBook.lyx文件，却是不同的编辑方向（译注：一个在创作，一个在修改）。记住Fossil没有锁定任何文件，没有任何东西阻止她编辑或修改当前我正在工作的文件。

这里我们都必须遵循流程以阻止这个问题的发生。尽管我看不到她所编辑的文件的修改，直到我们都将修改提交主仓库。在我已经提交了且她的使用的是当前最新版本时,同一文件拥有二个版本并不是问题。

\label{There-are-two}这里有二个问题：
\begin{enumerate}
\item 在我开始任何工作前我必须保证我拥有所有文件的当前最新版本
\item 当我提交时我必须保证我的修改部分不是她已经修改的部分
\end{enumerate}
第一个问题是非常明显的，在你工作前保证你有最新版本。我们通过使用Update命令来实现更新。见图示\ref{fig:Cloned-repository-checkin}，我完成了最新的检入操作。在开始任何工作前我应该保证Marilyn没有检入其它的文件。我可以检查时间线但是我将替代使用更新操作更新我的仓库和源码文件。当我更新时，我指定它需要从\textbf{trunk}更新。这个保证了我是从最新的仓库更新而不是其它什么分支。

\begin{figure}
\begin{lyxcode}
{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%~}\textbf{\scriptsize fossil~update~trunk}{\scriptsize \par}

{\scriptsize Autosync:~http://jim@pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi}{\scriptsize \par}

{\scriptsize Bytes~Cards~Artifacts~Deltas}{\scriptsize \par}

{\scriptsize Send:~130~1~0~0}{\scriptsize \par}

{\scriptsize Received:~3588~78~0~0}{\scriptsize \par}

{\scriptsize Send:~365~6~0~0}{\scriptsize \par}

{\scriptsize Received:~136461~83~2~3}{\scriptsize \par}

{\scriptsize Total~network~traffic:~796~bytes~sent,~131582~bytes~received}{\scriptsize \par}

{\scriptsize UPDATE~fossilbook.lyx}{\scriptsize \par}

{\scriptsize UPDATE~fossilbook.pdf}{\scriptsize \par}

{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}~
\end{lyxcode}
\caption{更新动作}


\end{figure}


哈哈！Marilyn已经在工作且更新了源码和PDF。如果我从网站服务器检查时间线查看，可以知道她甚至写了相关的文档：

\begin{figure}[H]
\includegraphics[scale=0.4]{Images/Multiple_user/mul_timeline}

\caption{更新后的时间线}


\end{figure}


现在我知道我有最新的状态了，我可以继续增加新章节的步骤了。


\subsection{复杂化\label{sub:Complications}}

在章节\vref{There-are-two}的第二个案例比较难。在这个案例里我开始工作前很勤快地进行了Fossil更新，同时Marilyn也完成了她的更新并开始了她的工作。现在她完成了并在对她的修改进行检查。很显然我不知道这些，因为我在高兴地进行我的修改工作。下面会发生什么... ...

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}\textbf{\scriptsize fossil~commit~-m~\textquotedbl{}Commit~that~might~fork\textquotedbl{}}{\scriptsize \par}

{\scriptsize Autosync:~http://jim@pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi}{\scriptsize \par}

{\scriptsize Bytes~Cards~Artifacts~Deltas}{\scriptsize \par}

{\scriptsize Send:~130~1~0~0}{\scriptsize \par}

{\scriptsize Received:~4002~87~0~0}{\scriptsize \par}

{\scriptsize Send:~365~6~0~0}{\scriptsize \par}

{\scriptsize Received:~110470~92~2~3}{\scriptsize \par}

{\scriptsize Total~network~traffic:~797~bytes~sent,~104567~bytes~received}{\scriptsize \par}

\textbf{\scriptsize fossil:~would~fork.~\textquotedbl{}update\textquotedbl{}~first~or~use~-f~or~-{}-force.}{\scriptsize \par}

{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}{\scriptsize \par}
\end{lyxcode}
\caption{作为分支提交}


\end{figure}


哈哈，恰好的事情发生了，Fossil警告我说我的文件副本与主仓库副本不一样。如果我添加强制提交的命令--force的话，仓库将会生成一个分支而Marilyn将来提交时会被提交到她的分支且我的提交只会提交到我的分支。那样不是我们想要的因为我想让她编辑\textbf{ }我的副本。

下一步按照Fossil说的需要更新我的副本。这样的话你必须得小心了，因为盲目地更新那些修改过的文件会覆盖我刚刚完成的东西。所以我们通过添加-n和-v选项参数来执行一个尝试更新，“执行一个不发行的更新”并且给我看看结果。

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%~fossil~update~-n~-v}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Multiple\_user/mul\_new\_user.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Multiple\_user/mul\_timeline.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Multiple\_user/test\_access.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/config\_initial.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/initial\_page.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/jim\_setup.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/ticket\_done.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/ticket\_form.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/ticket\_initial.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/ticket\_list.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/ticket\_submit.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/timeline.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/timeline\_detail.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/user\_config.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/wiki\_blankhome.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/wiki\_formating.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/wiki\_home.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/wiki\_homeedit.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Images/Single\_user/wiki\_page.epsf}{\scriptsize \par}

{\scriptsize UNCHANGED~Layout/fossil.png}{\scriptsize \par}

{\scriptsize UNCHANGED~Research/History/CVS-grune.pdf}{\scriptsize \par}

{\scriptsize UNCHANGED~Research/History/RCS\textemdash{}A~System~for~Version~Control.webloc}{\scriptsize \par}

{\scriptsize UNCHANGED~Research/History/SCCS-Slideshow.pdf}{\scriptsize \par}

{\scriptsize UNCHANGED~Research/History/VCSHistory~-~pysync~-~A~Brief~History~of~Version~Control~Systems~-~Project~Hosting~on~Google~Code.webloc}{\scriptsize \par}

{\scriptsize UNCHANGED~Research/fossilbib.bib}{\scriptsize \par}

{\scriptsize MERGE~fossilbook.lyx}{\scriptsize \par}

{\scriptsize UPDATE~fossilbook.pdf}{\scriptsize \par}

{\scriptsize UNCHANGED~outline.txt}{\scriptsize \par}

{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}{\scriptsize \par}
\end{lyxcode}
\caption{不发行的更新}


\end{figure}


如你所见，几乎所有的东西都是UNCHANGED，我要做的不多除了fossilbook.lyx需要合并（ MERGE）及fossilbook.pdf需要更新（UPDATE）。这就是我所期望的，Marilyn对文件fossilbook.lyx完成了她的修改工作，所有我们必须要合并她的修改。但是她还更新了fossilbook.pdf而我没有这个版本。在我们继续工作之前，如果你在使用Linux或者UNIX系统，你可以如下执行一个不发行的动作：

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}\textbf{\scriptsize fossil~update~-n~-v~|~grep~-v~UNCHANGED}{\scriptsize \par}

{\scriptsize MERGE~fossilbook.lyx}{\scriptsize \par}

{\scriptsize UPDATE~fossilbook.pdf}{\scriptsize \par}
\end{lyxcode}
\caption{小范围的不发行更新}


\end{figure}


通过使用管道和grep命令，我可以消除所有没有变更的条目。

\subsection{修复更新文件}

首先我们修复比较简单的文件，对于fossilbook.pdf我可以直接更新它到仓库当前版本以实现与其匹配。它不需要被合并所以只要替换它就可以了。在我做这一步之前我需要查看时间线。

\begin{figure}[H]
\includegraphics[scale=0.5]{Images/Multiple_user/mul_timeline}

\caption{当前的时间线}


\end{figure}


我看到当前的\textbf{ Leaf}（片段）是{[}d44769cc23{]}且它被标识为\textbf{ trunk}。我想要从它那里更新fossilbook.pdf这个文件，那么我输入：

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}\textbf{\scriptsize fossil~update~trunk~fossilbook.pdf}{\scriptsize \par}

{\scriptsize Autosync:~~http://jim@pandora.dyn-o-saur.com:8080/cgi-bin/Book.cgi}{\scriptsize \par}

{\scriptsize{}~~~~~~~~~~~~~~~~Bytes~~~~~~Cards~~Artifacts~~~~~Deltas}{\scriptsize \par}

{\scriptsize Send:~~~~~~~~~~~~~130~~~~~~~~~~1~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Received:~~~~~~~~4002~~~~~~~~~87~~~~~~~~~~0~~~~~~~~~~0}{\scriptsize \par}

{\scriptsize Total~network~traffic:~334~bytes~sent,~2412~bytes~received}{\scriptsize \par}

{\scriptsize UPDATE~fossilbook.pdf}{\scriptsize \par}

{\scriptsize {[}Pandora-2:jschimpf/Public/FossilBook{]}~jim\%}{\scriptsize \par}
\end{lyxcode}
\caption{更新fossilbook.pdf}

\end{figure}

好了，它完成了更新。


\subsection{修复合并文件}

我们可以使用Fossil内建的工具。这当前这个案例提示如果提交的话将产生一个分支Jim将会使用--force选项来创建分支并且稍后处理合并的问题。

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize E:\textbackslash{}Profile\textbackslash{}Ratte\textbackslash{}data\textbackslash{}organize\textbackslash{}fossil-w32\textbackslash{}fossil-book>fossil~commit~-m~\textquotedbl{}adding~some~changes~of~jim\textquotedbl{}}{\scriptsize \par}

{\scriptsize fossil:~would~fork.0~\textquotedbl{}update\textquotedbl{}~first~or~use~-f~or~-{}-force.}{\scriptsize \par}

{\scriptsize }{\scriptsize \par}

{\scriptsize E:\textbackslash{}Profile\textbackslash{}Ratte\textbackslash{}data\textbackslash{}organize\textbackslash{}fossil-w32\textbackslash{}fossil-book>fossil~commit~-f~-m~\textquotedbl{}adding~some~other~changes~of~jim\textquotedbl{}}{\scriptsize \par}

{\scriptsize New\_Version:~df9f2ff6b14ef65a9dd2162f8bd20c78e1628165}{\scriptsize \par}
\end{lyxcode}
\caption{命令窗口的强制提交}
\end{figure}


现在的时间线如下图所示：

\begin{figure}[H]
\includegraphics[scale=0.5]{Images/Multiple_user/Windows/forked_timeline}

\caption{已分支的时间线}
\end{figure}


我们使用Fossil的合并命令来删除这个分支（如：将Marilyn的变更内容纳入到trunk里）。我们可以使用merge是因为fossilbook.lyx是一个文本文件，而Merge命令的作者将其设计为可以在文本文件上进行工作的命令。如果它是一个二进制的文件我们必须使用一个外部程序或者使用对应文件格式的处理程序来复制黏贴来合并二进制文件。

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize E:\textbackslash{}Profile\textbackslash{}Ratte\textbackslash{}data\textbackslash{}organize\textbackslash{}fossil-w32\textbackslash{}fossil-book>fossil~merge~a91582b699}{\scriptsize \par}

{\scriptsize MERGE~fossilbook.lyx}{\scriptsize \par}

{\scriptsize {*}{*}{*}{*}{*}~2~merge~conflicts~in~fossilbook.lyx}{\scriptsize \par}
\end{lyxcode}
\caption{Fossil合并}
\end{figure}


在文本编辑器里查看文件(fossilbook.lyx)(不是\LyX{})我们发现：

\begin{figure}[H]
\begin{lyxcode}
{\scriptsize >\textcompwordmark{}>\textcompwordmark{}>\textcompwordmark{}>\textcompwordmark{}>\textcompwordmark{}>\textcompwordmark{}>~BEGIN~MERGE~CONFLICT}{\scriptsize \par}

{\scriptsize Thanks~to~Fossil's~distributed~design~once~the~set~up~is~done~using~it}{\scriptsize \par}

{\scriptsize with~multiple~users~is~not~much~different~than~the~single~user~case.}{\scriptsize \par}

{\scriptsize Fossil~will~automatically~manage~the~most~multiple~user~details.}{\scriptsize \par}

{\scriptsize ============================}{\scriptsize \par}

{\scriptsize }{\scriptsize \par}

{\scriptsize Thanks~to~Fossil's~distributed~design~once~the~set~up~is~done~using~is}{\scriptsize \par}

{\scriptsize not~much~different~than~the~single~user~case~with~Fossil~managing~automatically}{\scriptsize \par}

{\scriptsize the~multiple~user~details.}{\scriptsize \par}

{\scriptsize <\textcompwordmark{}<\textcompwordmark{}<\textcompwordmark{}<\textcompwordmark{}<\textcompwordmark{}<\textcompwordmark{}<~END~MERGE~CONFLICT}{\scriptsize \par}



\textbf{<Here~edit~in~the~changes>}



{\scriptsize E:\textbackslash{}Profile\textbackslash{}Ratte\textbackslash{}data\textbackslash{}organize\textbackslash{}fossil-w32\textbackslash{}fossil-book>fossil~commit~-m~\textquotedbl{}merging~marilyn's~fork~back\textquotedbl{}}{\scriptsize \par}

{\scriptsize New\_Version:~acdd676d3ab157769496f6845ccc7652985c1d03}{\scriptsize \par}
\end{lyxcode}
\caption{文本的不同之处}
\end{figure}


在完成提交之后，时间线告诉我们如何将分支合并到了主分支。Marilyn将需要更新到这个心的分支。(见章节\vref{sub:Updating-by-others})

\begin{figure}[H]
\includegraphics[scale=0.5]{Images/Multiple_user/Windows/merged_timeline}

\caption{合并的时间线}
\end{figure}


